﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleRest.Core.Extensions.Handlers;
using SimpleRest.Core.Routing;
using System.Web.Routing;
using SimpleRest.Core.Extensions.Routes;
using SimpleRest.Core.Extensions.Exceptions;

namespace SimpleRest.Core.Extensions
{
    public static class ConfigurationFactory
    {
        static ConfigurationFactory()
        {
            SimpleRest.Core.Routing.RouteUtility.OperationRouteRegistered += new OperationRouteRegisteredHandler(RouteUtility_OperationRouteRegistered);
            SimpleRest.Core.Routing.RouteUtility.ServiceRouteRegistered += new ServiceRouteRegisteredHandler(RouteUtility_ServiceRouteRegistered);
            SimpleRest.Core.Routing.RouteUtility.HttpRequestBodyResolved += new HttpRequestBodyResolvedEventHandler(RouteUtility_HttpRequestBodyResolved);
        }

        static void RouteUtility_HttpRequestBodyResolved(Type service, Operation operation, object body)
        {
            if (body != null)
            {
                var config = RouteUtility.GetRegisteredServices().FirstOrDefault(d => d.ServiceType.FullName == service.FullName).Configuration;
                if (config != null && config is ExtendedConfiguration && (config as ExtendedConfiguration).IsDataAnnotationValidationEnabled)
                {
                    ValidationUtility.RecursiveValidation(body);
                }
            }
        }

        static void RouteUtility_ServiceRouteRegistered(ServiceRoute route)
        {
            if (route.Configuration is ExtendedConfiguration && (route.Configuration as ExtendedConfiguration).IsAutoServiceDescriptionEnabled)
            {
                var pipeline = new Pipeline(route.ServiceType);

                var operationRoute = RouteUtility.Routes.FirstOrDefault(d => d is Route && (d as Route).Url.Trim(new char[] { '/' }) == route.RouteUri.Trim(new char[] { '/' })) as Route;
                var descriptionRoute = new DescriptionRoute(pipeline, route.Configuration, route.RouteUri, operationRoute);
                RouteUtility.Routes.Insert(0, descriptionRoute);
            }
        }

        static void RouteUtility_OperationRouteRegistered(OperationRoute operation, System.Web.Routing.Route route)
        {
            if (operation.Configuration is ExtendedConfiguration)
            {
                if ((operation.Configuration as ExtendedConfiguration).IsAutoXsdRoutingEnabled)
                {
                    var existingRoute = RouteUtility.Routes.FirstOrDefault(d => d is Route && (d as Route).Url.Trim(new char[] { '/' }) == operation.RouteUri.TrimEnd(new char[] { '/' }) + ".XSD");

                    if (existingRoute == null)
                    {
                        XsdRoute xsdRoute = new Routes.XsdRoute(new Pipeline(operation.ServiceType), operation.Configuration, operation.RouteUri, route, operation.TargetMethod.ReturnType);
                        RouteUtility.Routes.Insert(0, xsdRoute);
                    }
                }

                if ((operation.Configuration as ExtendedConfiguration).IsSampleResponseEnabled)
                {
                    var existingRoute = RouteUtility.Routes.FirstOrDefault(d => d is Route && (d as Route).Url.Trim(new char[] { '/' }) == operation.RouteUri.TrimEnd(new char[] { '/' }) + ".SAMPLE");

                    if (existingRoute == null)
                    {
                        Routes.SampleResponseRoute responseRoute =
                            new Routes.SampleResponseRoute(new Pipeline(operation.ServiceType), operation.Configuration, operation.RouteUri, route, operation.TargetMethod.ReturnType);
                        RouteUtility.Routes.Insert(0, responseRoute);
                    }
                }
            }
        }
      
        public static ExtendedConfiguration CreateConfiguration(
            bool isXsdDescriptionEnabled = true, 
            bool isCorrelationHandlerEnabled = true, 
            bool isAutoServiceDescriptionEnabled = true, 
            bool isDataAnnotationValidationEnabled = true,
            bool isSampleResponseEnabled = true)
        {
            var config = new ExtendedConfiguration();

            if (isCorrelationHandlerEnabled)
                config.MessageHandlers.Add(new CorrelationMessageHandler());

            config.IsAutoXsdRoutingEnabled = isXsdDescriptionEnabled;
            config.IsCorrelationHandlerEnabled = isCorrelationHandlerEnabled;
            config.IsAutoServiceDescriptionEnabled = isAutoServiceDescriptionEnabled;
            config.IsDataAnnotationValidationEnabled = isDataAnnotationValidationEnabled;
            config.IsSampleResponseEnabled = isSampleResponseEnabled;

            return config;
        }
    }
}
